#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/mman.h>
#include <linux/idr.h>
#include <linux/fb.h>
#include <linux/spi/spi.h>
#include <linux/proc_fs.h>
#include <linux/hrtimer.h>
#include <linux/ipcbus.h>
#include <linux/random.h>
#include <linux/miscdevice.h>
#include <linux/bitrev.h>
#include <linux/ktime.h>
#include <linux/i2c.h>
#include <asm/uaccess.h>
#include <plat/fb.h>
#include <plat/syncproc.h>
#include <plat/highres_timer.h>
#include <plat/cache.h>
#include <plat/event.h>
#include <mach/spi.h>
#include <mach/event.h>
#include <mach/board.h>
#include <mach/rct.h>
#include <mach/io.h>
#include <linux/kdev_t.h>
#include <sgks6802.h>

#include "sensor_version.h"

#include "sensor_common.h"
#include "sgks_vin.h"
#include "mpi_common.h"

//*****************************************************************************
//*****************************************************************************
//** sensor drvconfig filename from insmod param
//*****************************************************************************
//*****************************************************************************

static char *ConfigFile[SGKS_SENSOR_IN_MAX] = {NULL};
static int ConfigFileNum;
module_param_array(ConfigFile, charp, &ConfigFileNum, 0644);
MODULE_PARM_DESC(ConfigFile, "Sensor driver configuration files");

//*****************************************************************************
//*****************************************************************************
//** Local Defines
//*****************************************************************************
//*****************************************************************************

// SENSOR IDs
#define GENERIC_SENSOR          (127)   //changed to 127 in new DSP firmware
#define MICRON_MT9T001          (1)
#define ALTASENS_PROCAMHD       (2)
#define SONY_ICX495CCD          (3)
#define MICRON_MT9P001          (4)     // micron 5meg, same for MT9P031
#define OV5260                  (5)
#define MICRON_MT9M002          (6)     // micron 1.6meg
#define MICRON_MT9P401          (7)
#define Altasens_ALTA3372       (8)
#define Altasens_ALTA5262       (9)
#define SONY_IMX017             (10)
#define MICRON_MT9N001          (11)    // micron 9meg
#define SONY_IMX039             (12)
#define MICRON_MT9J001          (13)    // micron 10meg
#define SEMCOYHD                (14)
#define SONYIMX044              (15)
#define OV5633                  (16)
#define OV9710                  (17)
#define OV9715                  (17)
#define MICRON_MT9V136          (18)
#define OV7720                  (19)
#define OV7725                  (19)
#define OV7740                  (20)
#define OV10620                 (21)
#define OV10630                 (21)
#define MICRON_MT9P031          (22)    // variant of micron5m
#define OV9810                  (23)
#define OV8810                  (24)
#define SONYIMX032              (25)
#define MICRON_MT9P014          (26)
#define OV2710                  (27)
#define OV2715                  (27)
#define OV5653                  (28)
#define SONYIMX035              (29)
#define MICRON_MT9M033          (30)
#define OV7962                  (31)
#define SEC_S5K4AWFX            (32)    // Samsung
#define OV14810                 (29)
#define SONYIMX072              (33)
#define SONYIMX122              (34)
#define SONYIMX121              (35)
#define MICRON_MT9T002          (32)
#define MICRON_AR0331           (42)
#define SAMSUNG_S5K5B3GX        (32)
#define MACH_PV6418             (50)

#define CONFIG_SENSOR_I2C_ADDR    (0x80>>1)

#define SGKS_VI_BASIC_PARAM_CALL(name, address, adapter, perm) \
	static int name##_addr = address; \
	module_param(name##_addr, int, perm); \
	static int adapter_id = adapter; \
	module_param(adapter_id, int, perm)

SGKS_VI_BASIC_PARAM_CALL(sgks_vin, CONFIG_SENSOR_I2C_ADDR, 0, 0644);

//*****************************************************************************
//*****************************************************************************
//** Local structures
//*****************************************************************************
//*****************************************************************************



//*****************************************************************************
//*****************************************************************************
//** API Functions
//*****************************************************************************
//*****************************************************************************
static int sgks_vin_open(struct inode *inode, struct file *filp);
static long sgks_vin_ioctl(struct file *filp, unsigned int cmd, unsigned long args);
static void sgks_vi_config_info(sgks_vi_adap_config_s *adap, sgks_vi_cap_info_s *win_info);
static void sgks_vi_set_video_capture_window(sgks_vi_cap_window_s *adap, sgks_vi_cap_info_s *win_info);
static void sgks_vi_config_min_HV_sync_width(sgks_vi_hv_sync_s *adap, sgks_vi_cap_info_s *win_info);
static void sgks_vi_set_vo_sync_start_line(u32 start_line, sgks_vi_cap_info_s *win_info);

//*****************************************************************************
//*****************************************************************************
//** Global Data
//*****************************************************************************
//*****************************************************************************
static struct class *sgks_vin_class;
static int sgks_vin_major = 244;
static int sgks_vin_minor = 0;
static const char *sgks_vin_name = "sgks_vin";
static struct cdev sgks_vin_cdev;
static struct cdev *sgks_vin_dev = NULL;
static struct i2c_driver i2c_driver_sgks_vin;
static struct i2c_device_id sgks_vin_idtable[] =
{
    { "sgks_vi0", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, sgks_vin_idtable);

static int                    g_enable_print_default_init_regs = 0;
static u32                    g_debug_print = 0;
SGKS_VI_SensorDrvCfgT        *g_p_drvcfg = NULL;
static sgks_vin_drv_info_s   *g_p_vin_drv_info  = NULL;
static sgks_vi_cap_info_s     g_vin_confg;
static sgks_vi_sensor_ex_op_s sensor_extern={0};
static u8 sensor_loaded = 0;
static u8 agc_reg_need_update = 0;
static u8 shs_reg_need_update = 0;
static u8 vmax_reg_need_update = 0;
static u8 mirror_reg_need_update = 0;
static u8 reset_active_level = -1;

static struct file_operations sgks_vin_fops =
{
    .owner          = THIS_MODULE,
    .unlocked_ioctl = sgks_vin_ioctl,
    .open           = sgks_vin_open,
};

//*****************************************************************************
//*****************************************************************************
//** include mipi csi funtions
//*****************************************************************************
//*****************************************************************************

#include "mipi_csi.c"

//*****************************************************************************
//*****************************************************************************
//** include sensor operation funtions
//*****************************************************************************
//*****************************************************************************

#include "sgks_sensor_ops.c"


//*****************************************************************************
//*****************************************************************************
//** Local Functions
//*****************************************************************************
//*****************************************************************************
static int sgks_vin_open(struct inode *inode, struct file *filp)
{
    filp->private_data = g_p_vin_drv_info;
    return 0;
}

static long sgks_vin_ioctl(struct file *filp, unsigned int cmd, unsigned long args)
{
    int ret = SGKS_SENSOR_OPERATION_FAIL;
    msg_t ioctl_msg;

    switch(cmd)
    {
        case SGKS_SENWOR_IOCTL_OPERATION:
        {
            ret = copy_from_user(&ioctl_msg, (msg_t __user *)args, sizeof(msg_t)) ? -EFAULT : SGKS_SENSOR_OPERATION_SUCCESS;

            #if 0
            debug_printk("args:0x%08x\n", args);
            debug_printk("msg_size:%d\n", ioctl_msg.msg_head.msg_size);
            debug_printk("msg_type:0x%08x\n", ioctl_msg.msg_head.msg_type);

            #endif

            if(ret != SGKS_SENSOR_OPERATION_SUCCESS)
            {
                ret = SGKS_SENSOR_OPERATION_ERR_DATA;
                break;
            }

            switch(ioctl_msg.msg_head.msg_type)
            {
                case SGKS_SENSOR_OPERATION_START:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_START", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_STREAM_START_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_stream_start(filp->private_data,(SGKS_VI_STREAM_START_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_RESET:
                {
                    ret = sensor_reset(filp->private_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GETVER:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_VER_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_SENSOR_VER_S),SGKS_SENSOR_OPERATION_FAIL);
                    memset(ioctl_msg.msg_data, 0, sizeof(SGKS_SENSOR_VER_S));
                    SGKS_SENSOR_VER_S *ver = (SGKS_SENSOR_VER_S *)ioctl_msg.msg_data;
                    sprintf(ver->version, "v2.0.1");
                    ret = SGKS_SENSOR_OPERATION_SUCCESS;
                    break;
                }

                case SGKS_SENSOR_OPERATION_GETCAPABILITY:
                {
                    CHECK_PARAM_SIZE("sgks_vi_src_capability_s", ioctl_msg.msg_head.msg_size,sizeof(sgks_vi_src_capability_s),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_capability(filp->private_data, (sgks_vi_src_capability_s *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_INIT_HW:
                {
                    ret = sensor_init_hw(filp->private_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GETINFO:
                {

                    CHECK_PARAM_SIZE("SGKS_VI_SRC_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SRC_INFO_S),SGKS_SENSOR_OPERATION_FAIL);

                    ret = sensor_get_info(filp->private_data,(SGKS_VI_SRC_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_VIDEOINFO:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SRC_VIDEO_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SRC_VIDEO_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_video_info(filp->private_data,(SGKS_VI_SRC_VIDEO_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_CHECK_VIDEO_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SRC_MODE_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SRC_MODE_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_check_video_mode(filp->private_data,(SGKS_VI_SRC_MODE_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_SHUTTER_INFO:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SHUTTER_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SHUTTER_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_shutter_info(filp->private_data,(SGKS_VI_SHUTTER_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_SENSOR_INFO:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SRC_SENSOR_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SRC_SENSOR_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_sensor_info(filp->private_data,(SGKS_VI_SRC_SENSOR_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_FPS:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_FPS", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_fps(filp->private_data,(u32)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_SHUTTER_TIME:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_SHUTTER_TIME", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_shutter_time(filp->private_data,*(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_AGC_DB:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_AGC_DB", ioctl_msg.msg_head.msg_size,sizeof(s32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_agc_db(filp->private_data,*(s32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_VIDEO_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_VIDEO_MODE_E", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_video_mode(filp->private_data, (u32)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_STILL_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_STILL_MODE", ioctl_msg.msg_head.msg_size,sizeof(s32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_still_mode(filp->private_data,(s32)ioctl_msg.msg_data);
                    break;
                }


                case SGKS_SENSOR_OPERATION_SET_LOW_LIGHT_AGC:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_STILL_MODE", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_low_light_agc(filp->private_data,(u32)ioctl_msg.msg_data);
                    break;
                }


                case SGKS_SENSOR_OPERATION_SET_SLOWSHUTTER_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_SLOWSHUTTER_MODE", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_slowshutter_mode(filp->private_data,(u32)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_MIRROR_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SRC_MIRROR_MODE_S", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_mirror_mode(filp->private_data, *(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_BAYER_PATTERN:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SET_BAYER_PATTERN", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_bayer_pattern(filp->private_data, *(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_BAYER_PATTERN:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_BAYER_PATTERN", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_bayer_pattern(filp->private_data, (u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_UPDATE_REG:
                {
                    ret = sensor_set_update_reg(filp->private_data);//
                    break;
                }

                case SGKS_SENSOR_OPERATION_DUMP_REG:
                {
                    ret = sensor_dump_reg(filp->private_data);  //
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_REG:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_REG_DATA_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_REG_DATA_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_reg(filp->private_data,(SGKS_VI_REG_DATA_S*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_REG:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_REG_DATA_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_REG_DATA_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_reg(filp->private_data,(SGKS_VI_REG_DATA_S*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SET_PRINT_DEFAULT_REG:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_PRINT_DEFAULT_REG", ioctl_msg.msg_head.msg_size,sizeof(int),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_set_print_default_reg(filp->private_data, *(int*)ioctl_msg.msg_data);
                    break;
                }


                case SGKS_SENSOR_OPERATION_GET_AGC_INFO:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_AGC_INFO_S", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_AGC_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_agc_info(filp->private_data,(SGKS_VI_AGC_INFO_S*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_FRAME_RATE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_FRAME_RATE", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_fps(filp->private_data,(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_GAIN_DB:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_GAIN_DB", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_gain_db(filp->private_data,(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_SHUTTER_TIME:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_SHUTTER_TIME", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_shutter_time(filp->private_data,(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_VIDEO_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_VIDEO_MODE", ioctl_msg.msg_head.msg_size,sizeof(u32*),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_video_mode(filp->private_data,(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_OPERATION_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_VI_SENSOR_OP_MODE_E", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_SENSOR_OP_MODE_E),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_op_mode(filp->private_data,(SGKS_VI_SENSOR_OP_MODE_E*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_MIRROR_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_MIRROR_MODE", ioctl_msg.msg_head.msg_size,sizeof(u32),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_mirror_mode(filp->private_data,(u32*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_GET_ALL_VIDEO_MODE:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_GET_SUPPORT_VIDEO_MODE", ioctl_msg.msg_head.msg_size,sizeof(SGKS_VI_RESOLUTION_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_get_all_video_mode(filp->private_data,(SGKS_VI_RESOLUTION_S*)ioctl_msg.msg_data);
                    break;
                }

                case SGKS_SENSOR_OPERATION_SENSOR_REG_DEBUG:
                {
                    CHECK_PARAM_SIZE("SGKS_SENSOR_OPERATION_SENSOR_REG_DEBUG", ioctl_msg.msg_head.msg_size,sizeof(SGKS_SENSOR_REG_DEBUG_INFO_S),SGKS_SENSOR_OPERATION_FAIL);
                    ret = sensor_reg_debug(filp->private_data,(SGKS_SENSOR_REG_DEBUG_INFO_S *)ioctl_msg.msg_data);
                    break;
                }

                default:
                {
                    ret  = SGKS_SENSOR_OPERATION_ERR_ID;
                    printk("sensor ioctl : operation id:0x%08x error!\n", ioctl_msg.msg_head.msg_type);
                    break;
                }

            }

            break;
        }

        default:
        {
            ret  = SGKS_SENSOR_OPERATION_ERR_ID;
            printk("sensor ioctl err!\n");
            break;
        }
    }

    ioctl_msg.msg_head.ack_flag = ret;

    if (copy_to_user((msg_t __user *)args, &ioctl_msg, sizeof(msg_t)) != 0)
    {
        return SGKS_SENSOR_OPERATION_ERR_SYS;
    }

    return ret;
}

static int __init sgks_vin_create_dev(int *major, int minor, int numdev, const char *name, struct cdev *cdev, struct file_operations *fops)
{
    dev_t dev_id;
    int ret;

    if(*major)
    {
        dev_id = MKDEV(*major, minor);
        ret = register_chrdev_region(dev_id, numdev, name);
    }
    else
    {
        ret = alloc_chrdev_region(&dev_id, 0, numdev, name);
        *major = MAJOR(dev_id);
    }

    if(ret)
    {
        printk("failed to get dev region for %s\n", name);
        return ret;
    }

    cdev_init(cdev, fops);
    cdev->owner = THIS_MODULE;
    ret = cdev_add(cdev, dev_id, 1);

    if(ret)
    {
        printk("cdev_add failed for %s, error = %d\n", name, ret);
        return ret;
    }

    printk("%s dev init done, dev_id = %d:%d\n", name, MAJOR(dev_id), MINOR(dev_id));

    /*create dev node*/

    sgks_vin_class = class_create(THIS_MODULE, sgks_vin_name);

    if (IS_ERR(sgks_vin_class))
    {
        printk("class_create error\n" );
        return -1;
    }

    sgks_vin_dev=device_create(sgks_vin_class, NULL, MKDEV(*major, minor), NULL,sgks_vin_name);

    return 0;
}



//*****************************************************************************
//*****************************************************************************
//** sensor driver probe
//*****************************************************************************
//*****************************************************************************

static int sgks_vin_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int errorCode = 0;
    int i = 0;

    /*malloc device info*/
    if (g_p_vin_drv_info== NULL)
    {
        g_p_vin_drv_info = kzalloc(sizeof(sgks_vin_drv_info_s), GFP_KERNEL);

        if(g_p_vin_drv_info == NULL)
        {
            errorCode = -ENOMEM;
            return errorCode;
        }
        memset(g_p_vin_drv_info, 0, sizeof(sgks_vin_drv_info_s));
    }
    else
    {
        errorCode = -1;
        printk("re sensor err\n");
        return errorCode;
    }

    if((errorCode = sgks_vin_create_dev(&sgks_vin_major, sgks_vin_minor, 1, sgks_vin_name, &sgks_vin_cdev, &sgks_vin_fops)) < 0)
    {
        if (g_p_vin_drv_info)
        {
            kfree(g_p_vin_drv_info);    
        }
        
        return -1;
    }

    // I2c Client
    i2c_set_clientdata(client, g_p_vin_drv_info);
    memcpy(&g_p_vin_drv_info->client, client, sizeof(g_p_vin_drv_info->client));
    g_p_vin_drv_info->client.addr = CONFIG_SENSOR_I2C_ADDR;
    strlcpy(g_p_vin_drv_info->client.name, sgks_vin_name, sizeof(g_p_vin_drv_info->client.name));

    //g_p_vin_drv_info->sensor_info[i].vin_handle = &g_vin_confg;
    //g_p_drvcfg = &g_p_vin_drv_info->sensor_info[0].drvcfg;
    //errorCode = sgks_vin_read_drvcfg_file(g_p_vin_drv_info, ConfigFile);
    if (errorCode)
    {
        if (g_p_vin_drv_info)
        {
            kfree(g_p_vin_drv_info);    
        }
        g_p_drvcfg = NULL;
        return -1;
    }
    
    //sensor_stream_start(pinfo, 0);

    printk("####################################################\n");
    printk("# sgks_vin.ko:\n"); 
    printk("#    svn version : r%s\n", SVNREVISION);    
    printk("#    build date  : %s\n", TIMESTAMP);
    printk("####################################################\n");

    return errorCode;
}

static int sgks_vin_remove(struct i2c_client *client)
{
    if (g_p_vin_drv_info!= NULL)
    {
        kfree(g_p_vin_drv_info);
        g_p_vin_drv_info= NULL;
    }

    return 0;
}

static struct i2c_driver i2c_driver_sgks_vin =
{
    .driver =
    {
        .name = "sgks_vin",
    },
    .id_table = sgks_vin_idtable,
    .probe    = sgks_vin_probe,
    .remove   = sgks_vin_remove,
};

static int __init sgks_vin_init(void)
{

    return i2c_add_driver(&i2c_driver_sgks_vin);

}

static void __exit sgks_vin_exit(void)
{
    i2c_del_driver(&i2c_driver_sgks_vin);
}

module_init(sgks_vin_init);
module_exit(sgks_vin_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("SGKS MICROELECTRONICS Inc.");
MODULE_DESCRIPTION("SGKS Sensor Driver");
